// @Author miaoqing
// @Date 2024/02/23 10:36:00
// @Desc
package logic

import (
	"core/command"
	"core/component/function"
	"core/component/logger"
	"core/network"
	"sync"
)

type GatewayClient struct {
	tcpClient  *network.TcpClient
	serverID   string
	serverAddr string
	playerId   uint64 //玩家id
	msgID      []uint32
	onMsg      sync.Once
}

func (gc *GatewayClient) registerGatewayMsgHandler() {
	gc.tcpClient.Router.Register(uint16(command.Command_ClientInOnline_Online), gc.clientInOnlineHandler)
	gc.tcpClient.Router.Register(uint16(command.Command_ClientOutOnline_Online), gc.clientOutOnlineHandler)
	gc.tcpClient.Router.Register(uint16(command.Command_GatewayForwardPacket_Server), gc.gatewayForwardPacketHandler)
}

func (gc *GatewayClient) msgToGateway() {
	msgSend := &command.RegisterToGateway{
		Msgids:     gc.msgID,
		ServerID:   ServerInstance().id,
		ProcIndex:  uint32(ServerInstance().processIdx),
		ServerAddr: ServerInstance().httpAddr,
	}
	gc.sendMsg(command.Command_RegisterToGateway_Server, msgSend)
}

func (gc *GatewayClient) checkConnect(srvAddr string) {
	if gc.tcpClient.IsRunning() {
		return
	}
	gc.connect(srvAddr)
}

func (gc *GatewayClient) connect(addr string) {
	if err := gc.tcpClient.Connect(addr); err != nil {
		logger.Error("[连接] Online->Gateway连接失败")
		return
	}
	gc.onMsg.Do(gc.registerGatewayMsgHandler)
	gc.msgToGateway()
	logger.Infof("[连接] Online->Gateway连接成功 SrvID:%v srvAddr:%v", gc.serverID, gc.serverAddr)
}

func (gc *GatewayClient) sendMsg(cmd command.Command, msg interface{}) bool {
	return gc.tcpClient.AsyncSend(uint16(cmd), msg)
}

func (gc *GatewayClient) sendMsgToClient(userID uint64, cmd command.Command, msg interface{}) bool {
	data, err := gc.tcpClient.Marshal(uint16(cmd), msg)
	if err != nil {
		logger.Errorf("send msg to client error msg id %v userID:%v", cmd, userID)
		return false
	}
	sendMsg := &command.GatewayForwardPacket{Userid: userID, PlayerNumber: 0, Data: data}
	gc.sendMsg(command.Command_GatewayForwardPacket_Server, sendMsg)
	return true
}

// 发送原始数据给客户端 data是个完整的原始消息包
func (gc *GatewayClient) sendRowMsgToClient(userID uint64, data []byte) bool {
	// 前端UI服列表顺序固定，避免前若干服，在开服前期被撑爆，对人数做特殊处理
	sendMsg := &command.GatewayForwardPacket{Userid: userID, PlayerNumber: function.CalcSyncMapLen(WorldGetMe().players)}
	sendMsg.Data = data
	gc.sendMsg(command.Command_GatewayForwardPacket_Server, sendMsg)
	return true
}

// OnCloseCallBack 连接断开回调
func (gc *GatewayClient) OnCloseCallBack() {
	//WorldGetMe().chanGatewayDown <- gc.serverID
	logger.Debugf("[连接] Gateway服务器连接断开 地址:%v", gc.serverID)
}

// gateway转发过来的消息统一放在这里处理 (clientID为客户端在gateway上的连接ID)
func (gc *GatewayClient) msgPacketHandle(userID uint64, data []byte) {
	// 先路由本地处理方法 找不到就交给world goroutine来处理
	msgID, err := gc.tcpClient.Router.Route(data)
	if err != nil {
		err = WorldGetMe().handlePlayersMsgPacket(userID, data)
	}
	if err != nil {
		logger.Errorf("route message:%v error: %v", msgID, err)
	}
}
